home *** CD-ROM | disk | FTP | other *** search
/ Amiga Game-Power / Amiga Game-Power.iso / pd mix ii / access / thai / say.c < prev    next >
C/C++ Source or Header  |  1994-05-20  |  6KB  |  308 lines

  1. #include "quiz.h"
  2.  
  3. #include "devices/narrator.h"
  4. #include "libraries/translator.h"
  5.  
  6. #include "trans.h"
  7.  
  8. #define MY_PITCH    (2*DEFPITCH)
  9.  
  10.  
  11. extern struct MsgPort *        CreatePort();
  12. extern struct IORequest *    CreateExtIO();    
  13. extern LONG                    Translate ();
  14. extern LONG                    OpenDevice ();
  15. extern struct Library *        OpenLibrary();
  16.  
  17.  
  18. struct Library *            TranslatorBase;
  19.  
  20. static struct MsgPort *        writeport;
  21. static struct narrator_rb *    writeNarrator;
  22. static UBYTE audChanMasks[4] = { 3,5,10,12 }; /* which channels to use */
  23.  
  24. static char                    outputstring[ 200 ];
  25.  
  26.  
  27. init_speech ()
  28. {
  29.     TranslatorBase = OpenLibrary ( "translator.library" , (LONG)2 );
  30.     if ( TranslatorBase == NULL )
  31.         return ( FALSE );
  32.  
  33.     writeport = CreatePort ( (LONG)0 , (LONG)0 );
  34.     if ( writeport == NULL ) {
  35.         CloseLibrary ( TranslatorBase );
  36.         return ( FALSE );
  37.     }
  38.  
  39.     writeNarrator = (struct narrator_rb *)
  40.         CreateExtIO ( writeport , (LONG) sizeof ( struct narrator_rb ) );
  41.     if ( writeNarrator == NULL ) {
  42.         DeletePort ( writeport );
  43.         CloseLibrary ( TranslatorBase );
  44.         return ( FALSE );
  45.     }
  46.  
  47. /* SET UP THE PARAMETERS FOR THE WRITE-MESSAGE TO THE NARRATOR DEVICE */
  48.  
  49.     writeNarrator->ch_masks = (audChanMasks);
  50.     writeNarrator->nm_masks = sizeof ( audChanMasks );    
  51.     writeNarrator->sex = MALE;
  52.     writeNarrator->mode = NATURALF0;
  53.     writeNarrator->pitch = MY_PITCH;  /* raise pitch from default value */
  54.     writeNarrator->rate = DEFRATE;
  55.     writeNarrator->mouths = FALSE;
  56.     writeNarrator->message.io_Command = CMD_WRITE;
  57.  
  58.     if ( OpenDevice ( "narrator.device" , (LONG)0 , writeNarrator , (LONG)0 )
  59.     != 0 ) {
  60.         DeleteExtIO ( writeNarrator , (LONG) sizeof ( struct narrator_rb ) );
  61.         DeletePort ( writeport );
  62.         CloseLibrary ( TranslatorBase );
  63.         return ( FALSE );
  64.     }
  65.  
  66.     return ( TRUE );
  67. }
  68.  
  69.  
  70. close_speech ()
  71. {
  72.     /* terminate access to the device */
  73.  
  74.     if ( writeNarrator != 0 )
  75.         CloseDevice ( writeNarrator );
  76.  
  77.     /* now return system memory to the memory allocator */ 
  78.  
  79.     if ( writeNarrator != 0 )
  80.         DeleteExtIO ( writeNarrator , (LONG) sizeof ( struct narrator_rb ) );
  81.  
  82.     if ( writeport != 0 )
  83.         DeletePort ( writeport );
  84.     
  85.     /* terminate access to the library */
  86.  
  87.     if ( TranslatorBase != NULL )
  88.            CloseLibrary ( TranslatorBase );
  89. }
  90.  
  91.  
  92. speak_english ( str )
  93. char *str;
  94. {
  95.  
  96.     Translate ( str , (LONG) strlen ( str ) , outputstring ,
  97.         (LONG) sizeof ( outputstring ) );
  98.     writeNarrator->message.io_Data = (APTR) outputstring;
  99.     writeNarrator->message.io_Length = strlen ( outputstring );
  100.     DoIO ( writeNarrator );
  101. }
  102.  
  103.  
  104. speak ( phonemes )
  105. char *phonemes;
  106. {
  107.     struct syllable syl;
  108.  
  109.     while ( trans_syllable ( &phonemes , &syl ) )
  110.         say_syllable ( &syl );
  111. }
  112.  
  113.  
  114. static
  115. say_syllable ( syl )
  116. struct syllable *syl;
  117. {
  118.     char *addstr;
  119.  
  120.  
  121.     addstr = ".";    /* need a punctuation mark at the end */
  122.  
  123.     switch ( syl->tone ) {
  124.  
  125.     case HIGH_TONE :
  126.         writeNarrator->mode = ROBOTICF0;
  127.         writeNarrator->pitch = MY_PITCH + 30;
  128.         break;
  129.  
  130.     case LOW_TONE :
  131.         writeNarrator->mode = ROBOTICF0;
  132.         writeNarrator->pitch = MY_PITCH - 30;
  133.         break;
  134.  
  135.     default :
  136.     case MIDDLE_TONE :
  137.         writeNarrator->mode = ROBOTICF0;
  138.         writeNarrator->pitch = MY_PITCH;
  139.         break;
  140.  
  141.     case RISING_TONE :
  142.         writeNarrator->mode = NATURALF0;
  143.         writeNarrator->pitch = MY_PITCH;
  144.         addstr = "?";
  145.         break;
  146.  
  147.     case FALLING_TONE :
  148.         writeNarrator->mode = NATURALF0;
  149.         writeNarrator->pitch = MY_PITCH + 30;
  150.         break;
  151.  
  152.     }
  153.  
  154.     strcpy ( outputstring , syl->phonemes );
  155.     strcat ( outputstring , addstr );
  156.  
  157.     writeNarrator->message.io_Data = (APTR) outputstring;
  158.     writeNarrator->message.io_Length = strlen ( outputstring );
  159.     writeNarrator->rate = DEFRATE / syl->duration;
  160.  
  161.     DoIO ( writeNarrator );
  162. }
  163.  
  164.  
  165. static struct {
  166.     char user_phoneme[8];
  167.     char amiga_phoneme[8];
  168.     int duration;
  169. } phoneme_table[] = {
  170.     { "AA" , "AE" , 2 } ,
  171.     { "AH" , "AH" , 2 } ,
  172.     { "AI" , "AY" , 2 } ,
  173.     { "AOU", "AW" , 2 } ,
  174.     { "AO" , "AW" , 2 } ,
  175.     { "AW" , "OH" , 2 } ,
  176.     { "A"  , "AH" , 1 } ,
  177.     { "BP" , "B/H", 1 } ,
  178.     { "B"  , "B"  , 1 } ,
  179.     { "CH" , "CH" , 1 } ,
  180.     { "DT" , "DX" , 1 } ,
  181.     { "D"  , "D"  , 1 } ,
  182.     { "EE" , "IY" , 2 } ,
  183.     { "EH" , "EH" , 2 } ,
  184.     { "ER" , "ER" , 2 } ,
  185.     { "EUA", "ERAH" , 2 } ,
  186.     { "EU" , "EHER" , 1 } ,    /* also EU bar duration 2 */
  187.     { "F"  , "F"  , 1 } ,
  188.     { "G"  , "G"  , 1 } ,
  189.     { "H"  , "/H" , 1 } ,
  190.     { "IA" , "IHAH",1 } ,
  191.     { "IH" , "IY" , 1 } ,
  192.     { "IW" , "IHW", 1 } ,
  193.     { "I"  , "IH" , 1 } ,
  194.     { "J"  , "J"  , 1 } ,
  195.     { "KH" , "K" , 1 } ,
  196.     { "K"  , "K"  , 1 } ,
  197.     { "L"  , "L"  , 1 } ,
  198.     { "M"  , "M"  , 1 } ,
  199.     { "NG" , "NX" , 1 } ,
  200.     { "N"  , "N"  , 1 } ,
  201.     { "OA" , "AW" , 2 } ,
  202.     { "OH" , "AA" , 2 } ,
  203.     { "OO-AY" , "UHEY" , 1 } ,
  204.     { "OO-A" , "UHA" , 1 } ,
  205.     { "OO-Y" , "OY" , 2 } ,
  206.     { "OOAY" , "UHEY" , 1 } ,
  207.     { "OOA" , "UHA" , 1 } ,
  208.     { "OOY" , "OY" , 2 } ,
  209.     { "OO" , "UH" , 1 } ,
  210.     { "OR" , "OH" , 1 } ,
  211.     { "OY" , "OY" , 1 } ,
  212.     { "P"  , "P"  , 1 } ,
  213.     { "R"  , "R"  , 1 } ,
  214.     { "S"  , "S"  , 1 } ,
  215.     { "T"  , "T"  , 1 } ,
  216.     { "UA" , "ERAH",1 } ,
  217.     { "UH" , "AH" , 2 } ,
  218.     { "UM" , "AHM", 1 } ,
  219.     { "U"  , "AH" , 1 } ,
  220.     { "W"  , "W"  , 1 } ,
  221.     { "Y"  , "Y"  , 1 } ,    /* y bar for long y */
  222.     { ""   , ""   , 0 }
  223. };
  224.  
  225.  
  226. static
  227. trans_syllable ( ip , syl )
  228. char **ip;
  229. struct syllable *syl;
  230. {
  231.     int i;
  232.  
  233.     syl->tone = MIDDLE_TONE;
  234.     syl->phonemes[0] = '\0';
  235.     syl->duration = 0;
  236.     while ( **ip == ' ' )
  237.         (*ip)++;
  238.     if ( **ip == '-' )
  239.         (*ip)++;
  240.     if ( **ip == '(' ) {
  241.         (*ip)++;
  242.  
  243.         switch ( mklower ( *(*ip)++ ) ) {
  244.  
  245.         case 'h' :
  246.             syl->tone = HIGH_TONE;
  247.             break;
  248.  
  249.         case 'm' :
  250.         case 'c' :
  251.         case 'n' :
  252.             syl->tone = MIDDLE_TONE;
  253.             break;
  254.  
  255.         case 'l' :
  256.             syl->tone = LOW_TONE;
  257.             break;
  258.  
  259.         case 'r' :
  260.             syl->tone = RISING_TONE;
  261.             break;
  262.  
  263.         case 'f' :
  264.         case 'd' :
  265.             syl->tone = FALLING_TONE;
  266.             break;
  267.         }
  268.         if ( **ip == ')' )
  269.             (*ip)++;
  270.     }
  271.     while ( **ip != '('  &&  **ip != ' '  &&  **ip != '\0' ) {
  272.         if ( **ip == '-' )
  273.             (*ip)++;
  274.         for ( i = 0; phoneme_table[i].user_phoneme[0] != '\0'; i++ ) {
  275.             if ( substr ( ip , phoneme_table[i].user_phoneme ) ) {
  276.                 strcat ( syl->phonemes , phoneme_table[i].amiga_phoneme );
  277.                 if ( syl->duration < phoneme_table[i].duration )
  278.                     syl->duration = phoneme_table[i].duration;
  279.                 break;
  280.             }
  281.         }
  282.         if ( phoneme_table[i].user_phoneme[0] == '\0' ) {    /* not found */
  283.             return ( FALSE );    /* best that can be done */
  284.         }
  285.         if ( **ip == '!' ) {
  286.             (*ip)++;
  287.             syl->duration = ( syl->duration + 1 ) / 2;
  288.         }
  289.     }
  290.     return ( syl->phonemes[0] != '\0' );
  291. }
  292.  
  293.  
  294. static
  295. substr ( buf , sub )
  296. char **buf , *sub;
  297. {
  298.     char *p;
  299.  
  300.     p = *buf;
  301.     while ( *sub != '\0' ) {
  302.         if ( *p++ != *sub++ )
  303.             return ( FALSE );
  304.     }
  305.     *buf = p;
  306.     return ( TRUE );
  307. }
  308.